"use strict";

// copy&paste from http://stackoverflow.com/questions/55677/how-do-i-get-the-coordinates-of-a-mouse-click-on-a-canvas-element
function relativeMousePosition(e, canvas) {
	var x;
	var y;
	if (e.pageX || e.pageY) { 
		x = e.pageX;
		y = e.pageY;
	}
	else { 
		x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft; 
		y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop; 
	} 
	x -= canvas.offsetLeft;
	y -= canvas.offsetTop;
	return $V([x, y]);
}

function GuiVar(simulator, renderer) {
	
	/* mode0, mode1
	
	     editor
	       default
	       moveSelection
	
	     simulation
	*/
	
	// permanent
	this.simulator = simulator;
	this.renderer = renderer;
	
	this.mode0 = "editor";
	this.mode1 = "default";
	this.mouseDown = [false, false, false, false, false, false, false, false, false];
	
	// editor
	this.nextObjectType = null;
	
	this.semiObjectType = null;
	this.semiObject = null;
	
	this.selectedObject = null;
	
	// simulation
	this.hSimulationInterval = null;
	this.wantedFps = 100.0;
	this.slowmotionFactor = 1.0;
	this.timeStep = 1.0/this.wantedFps/this.slowmotionFactor;
	this.damping = 0.7;
	this.skipFrames = 2;
	
	this.gravity = new Simulatable.Gravity($V([0.0, -9.8]));
	this.heavyPoint = new Simulatable.MassPoint(Number.POSITIVE_INFINITY);
	
	this.onMouseDown = function(e) {
		this.mouseDown[e.button] = true;
		
		if (this.mode0 == "editor") {
			// select new object
			if (this.mode1 == "default") {
				if (this.mouseDown[0]) {
					this.mode1 = "moveSelection";
				}
				if (this.mouseDown[2]) {
					if (this.objectType == "lightSteel") {
						var radius = 0.1;
						var youngsModulus =  500;
						var density = 2;
						var internalFriction = 3;
					}
					if (this.objectType == "heavySteel") {
						var radius = 0.1;
						var youngsModulus = 5000;
						var density = 10;
						var internalFriction = 50;
					}
					if (this.objectType == "lightSteel" || this.objectType == "heavySteel") {
						// node0
						{
							var node0 = new Simulatable.Node($V([0.0 , 0.0]));
							var renderNode0 = new Renderables.Node(node0);
							renderNode0.setPixelPosition(this.renderer, relativeMousePosition(e, this.renderer.getCanvas()));
							
							this.simulator.nodes.push(node0);
							this.renderer.objects.push(renderNode0);
						}
						// rod
						var rod = new Simulatable.Rod(length, radius, youngsModulus, density, internalFriction);
						var renderRod = new Renderables.Rod(rod);
						this.simulator.elements.push(rod);
						this.renderer.objects.push(renderRod);
						
						// node1
						{
							var node1 = new Simulatable.Node($V([0.0 , 0.0]));
							var renderNode1 = new Renderables.Node(node1);
							renderNode1.setPixelPosition(this.renderer, relativeMousePosition(e, this.renderer.getCanvas()));
							
							this.simulator.nodes.push(node1);
							this.renderer.objects.push(renderNode1);
						}
						
						node0.addPort(this.gravity);
						node1.addPort(this.gravity);
						
						this.simulator.connectNodeAndPort(node0, rod.ports[0]);
						this.simulator.connectNodeAndPort(node1, rod.ports[1]);
						
						if (this.selectedObject != null && this.selectedObject.name == "renderableNode") {
							simulator.mergeSecondNodeToFirst(this.selectedObject.physicsNode, node0);
							
							this.simulator.nodes.splice(this.simulator.nodes.indexOf(node0), 1);
							this.renderer.objects.splice(this.renderer.objects.indexOf(renderNode0), 1);
						}
						
						this.setSelectedObject(renderNode1);
						
						this.mode1 = "moveSelection";
					}
					if (this.objectType == "fixedPoint") {
						var node = null;
						var renderNode = this.selectedObject;
						// node0
						if (renderNode != null && renderNode.name == "renderableNode") {
							node = renderNode.physicsNode;
						} else {
							node= new Simulatable.Node($V([0.0 , 0.0]));
							renderNode = new Renderables.Node(node);
							renderNode.setPixelPosition(this.renderer, relativeMousePosition(e, this.renderer.getCanvas()));
							
							this.simulator.nodes.push(node);
							this.renderer.objects.push(renderNode);
						}
						node.addPort(this.heavyPoint);
					}
				}
			}
		}
	}
	
	this.onMouseUp = function(e) {
		this.mouseDown[e.button] = false;
		
		if (this.mode0 == "editor") {
			if (this.mode1 == "moveSelection") {
				if (this.selectedObject != null && this.selectedObject.name == "renderableNode") {
					var node = this.selectedObject.physicsNode;
					for (var inrnode in this.renderer.objects) {
						var nrnode = this.renderer.objects[inrnode];
						if (nrnode.name == "renderableNode") {
							var nnode = nrnode.physicsNode;
							if (node != nnode && nnode.position.subtract(node.position).modulus()*this.renderer.lengthScale < 10.0) {
								this.simulator.mergeSecondNodeToFirst(node, nnode);
								
								this.simulator.nodes.splice(this.simulator.nodes.indexOf(nnode), 1);
								this.renderer.objects.splice(this.renderer.objects.indexOf(nrnode), 1);
							}
						}
					}
				}
			}
			this.mode1 = "default";
		}
	}
	
	this.onMouseMove = function(e) {
		if (this.mode0 == "editor") {
			// console.log("---");
			// console.log(relativeMousePosition(e, renderer.getCanvas()).elements);
			// console.log(renderer.pixels2PhysicsCoords(relativeMousePosition(e, renderer.getCanvas())).elements);
			
			if (this.mode1 == "default") {
				this.setSelectedObject(renderer.getObjectAtPixels(relativeMousePosition(e, renderer.getCanvas())));
			}
			if (this.mode1 == "moveSelection") {
				if (this.selectedObject != null) {
					// lbm down => move object
					this.selectedObject.setPixelPosition(renderer, relativeMousePosition(e, renderer.getCanvas()));
					for (e in this.simulator.elements) {
						var element = this.simulator.elements[e];
						if (element.name == "rod") {
							element.length = element.ports[0].node.position.subtract(element.ports[1].node.position).modulus();
						}
					}
				}
			}
			this.renderer.render();
		}
	}
	
	this.onDblClick = function(e) {
		if (this.mode0 == "editor") {
			if (this.mode1 == "moveSelection") {
			}
		}
	}
	
	this.setSelectedObject = function(newObject) {
		if (this.selectedObject != null) {
			this.selectedObject.setSelected(false);
		}
		this.selectedObject = newObject;
		if (this.selectedObject != null) {
			this.selectedObject.setSelected(true);
		}
	}
	
	this.setObjectType = function(typeName) {
		this.objectType = typeName;
	}
	
	this.startSimulation = function() {
		if (this.mode0 != "simulation") {
			this.mode0 = "simulation";
			this.mode1 = "";
			
			this.simulator.setZeroVelocity(simulator.nodes);
			
			var reachedFps = 0.0;
			var lastTime = null;
			var this_ = this;
			var cnt = 0;
			this.hSimulationInterval = setInterval( function() {
				var oldTime = lastTime;
				var curTime = new Date().getTime();
				lastTime = curTime;
				this_.simulator.advanceTime(this_.timeStep, this_.damping);
				if (cnt % this_.skipFrames == 0) {
					this_.renderer.render();
					if (oldTime != null) {
						this_.renderer.getContext().fillText(Math.round(reachedFps) + " fps", 0, 20);
					}
				}
				reachedFps = 0.98*reachedFps + 0.02*1000.0/(curTime - oldTime);
				cnt++;
			}, 1000.0/this_.wantedFps );
		}
	}
	
	this.startEditor = function() {
		if (this.mode0 != "editor") {
			this.mode0 = "editor";
			this.mode1 = "default";
			clearInterval(this.hSimulationInterval);
			this.hSimulationInterval = null;
		}
	}
}
